/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package lab3serveurhttp;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.FileNameMap;
import java.net.Socket;
import java.net.URLConnection;
/**
 *
 * @author Mathieu
 */
public class HTTPConnectionHandler implements Runnable
{
   private static final String BASEDIR = "web";
   Socket s;
   FileNameMap fileNameMap;

   public HTTPConnectionHandler (Socket clientSocket)
   {
       this.s=clientSocket;
       fileNameMap = URLConnection.getFileNameMap();
   }

    public void run ()
    {
        try
        {
            HTTPRequestHeader requestHeader = new HTTPRequestParser(s.getInputStream()).parse();
            HTTPResponseHeader responseHeader = new HTTPResponseHeader ( );
            File file = null;
            InputStream is = null;
            long length = 0;

            try
            {
                System.out.println ( "Page demandée par " + s.getInetAddress().getHostAddress() + ":" + java.net.URLDecoder.decode ( requestHeader.Get, "UTF-8" ) );
                file = openFile ( BASEDIR + java.net.URLDecoder.decode ( requestHeader.Get, "UTF-8" ) ); 
                responseHeader.setContentType(fileNameMap.getContentTypeFor(file.getPath()));
                length = file.length();
                responseHeader.setContentLength(length);
                is = new FileInputStream(file);   
            }
            catch ( HTTPException ex )
            {
                responseHeader.setState(ex.getState());
            }
            catch ( Exception ex )
            {
                responseHeader.setState ( HTTPState.INTERNAL_ERROR );
            }

            if ( responseHeader.getState().equals(HTTPState.OK))
            {
                s.getOutputStream().write(responseHeader.toString().getBytes());
                
                try
                {     
                    long bytesRead = 0;
                    int blockSize = 1024;                        

                    while ( bytesRead < length )
                    {
                        int contentSize = (int)(( length - bytesRead < blockSize )? length - bytesRead : blockSize);
                        byte [] content = new byte [contentSize];
                        is.read(content);
                        s.getOutputStream().write(content);
                        bytesRead += contentSize;
                    }
                }
                catch ( Exception e )
                {
                    System.out.println ( e.getMessage() );
                }
                finally
                {
                    is.close();
                }
            }
            else
            {
                HTTPState state = responseHeader.getState();
                String errorMessage = "<html><body><h1>" + state.getValue() + " " + state + "</h1></body></html>";
                responseHeader.setContentLength(errorMessage.length());
                s.getOutputStream().write(responseHeader.toString().getBytes());
                s.getOutputStream().write( errorMessage.getBytes() );
            }
        }
        catch (Exception e)
        {
            System.out.println ( e.getMessage() );
        }
        finally
        {
            try
            {
                this.s.close();
            }
            catch (Exception e){}
        }
    }

    private File openFile ( String path ) throws HTTPException
    {
        try
        {
            File file = new File ( path ).getCanonicalFile();

            if ( ! file.getPath().startsWith(new File ( BASEDIR ).getCanonicalFile().getPath()) )
                throw new HTTPException ( HTTPState.FORBIDDEN );

            if ( ! file.exists() )
                throw new HTTPException ( HTTPState.NOT_FOUND );

            if ( ! file.canRead() )
                throw new HTTPException ( HTTPState.FORBIDDEN );

            if ( file.isDirectory() )
                return openFile ( path + "/index.html" );
            else
                return file;
        }
        catch ( IOException ioe )
        {
            throw new HTTPException ( HTTPState.INTERNAL_ERROR );
        }
    }



}
